package com.jprocms.module.cms.service.staticpage;

import com.jprocms.module.cms.dal.dataobject.content.ContentDO;
import com.jprocms.module.cms.dal.dataobject.task.TaskDO;
import com.jprocms.module.cms.enums.EnumContentStatus;
import com.jprocms.module.cms.enums.EnumTask;
import com.jprocms.module.cms.service.content.ContentService;
import com.jprocms.module.cms.service.task.TaskService;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.time.OffsetDateTime;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.LongConsumer;

/**
 * 生成器抽象类
 *
 * @author jprocms
 */
public abstract class AbstractProducer {
    protected ContentService contentService;
    protected TaskService taskService;
    private final ThreadPoolTaskExecutor executor;

    protected AbstractProducer(ContentService contentService, TaskService taskService,
                               ThreadPoolTaskExecutor executor) {
        this.contentService = contentService;
        this.taskService = taskService;
        this.executor = executor;
    }

    protected void execute(Long taskSiteId, Long taskUserId, String taskName, short taskType,
                           boolean deleteOnFinished, LongConsumer consumer) {
        TaskDO task = new TaskDO(taskSiteId, taskUserId, taskName, taskType);
        // 等待状态，在队列里等待线程池运行
        taskService.createTask(task);
        Long taskId = task.getId();
        executor.execute(() -> {
            try {
                TaskDO bean = taskService.getTask(taskId);
                // 任务有可能被删除或停止
                if (bean == null || bean.getStatus() != EnumTask.STATUS_WAITING.getStatus()) {
                    return;
                }
                bean.setStatus(EnumTask.STATUS_RUNNING.getStatus());
                taskService.updateTask(bean);
                consumer.accept(taskId);
                bean = taskService.getTask(taskId);
                if (bean == null) {
                    return;
                }
                if (deleteOnFinished && bean.getStatus() == EnumTask.STATUS_RUNNING.getStatus()) {
                    // 结束删除任务
                    taskService.deleteTask(taskId);
                } else {
                    // 正常完成任务
                    bean.setEndTime(OffsetDateTime.now());
                    bean.setStatus(EnumTask.STATUS_DONE.getStatus());
                    taskService.updateTask(bean);
                }
            } catch (Exception e) {
                // 记录错误信息
                TaskDO bean = taskService.getTask(taskId);
                if (bean == null) {
                    return;
                }
                bean.setError(e);
                taskService.updateTask(bean);
            }
        });
    }

    void handleContent(Long taskId, Long siteId, Consumer<ContentDO> consumer) {
        Long minId = 0L;
        int offset = 0;
        int limit = 100;
        int size = limit;
        //从最小id查询，每100条一次查询，>=100 说明还有下一页数据需要继续处理，minId继续查询
        while (size >= limit) {
            List<ContentDO> list = contentService.getListByMinId(minId, siteId, EnumContentStatus.PUBLISHED.getStatus(), offset, limit);
            size = list.size();
            for (int i = 0; i < size; i++) {
                ContentDO content = list.get(i);
                consumer.accept(content);
                if (i == size - 1) {
                    minId = content.getId();
                }
            }
            if (updateTask(taskId, size)) {
                break;
            }
        }
    }

    /**
     * 更新任务
     *
     * @param taskId 任务ID
     * @param size   完成数量
     * @return 是否中止任务
     */
    protected boolean updateTask(Long taskId, int size) {
        TaskDO task = taskService.getTask(taskId);
        // 任务被删，中止任务
        if (task == null) {
            return true;
        }
        task.setCurrentNum(task.getCurrentNum() + size);
        taskService.updateTask(task);
        return task.getStatus() == EnumTask.STATUS_STOP.getStatus();
    }
}
